library(diprate)
library(ggplot2)
library(viridis)
Loading required package: viridisLite
library(tidyr)
library(ggridges)
library(dplyr)

Attaching package: ‘dplyr’

The following objects are masked from ‘package:stats’:

    filter, lag

The following objects are masked from ‘package:base’:

    intersect, setdiff, setequal, union

Function to quantify ppERK using both proportion of positive cells and the avg intensity

Using both proportion of cells staining positively for ppERK and the integrated values of the positive cells.

ppERKint <- function(dat, signif=4) {
    cell_count <- nrow(dat)
    pos_cells <- nrow(dat[dat$positive.w2==1,])
    val <- pos_cells/cell_count*sum(dat[dat$positive.w2==1,]$avg.pERK)
    val <- signif(val,signif)
    return(val)
}

Load data

d <- read.csv("https://www.dropbox.com/scl/fi/mty3qbhtu917pbrvra5kj/202402119_singlecell_all_cpa.csv?rlkey=9fmn41fu22p1l0lpkwf1d21nw&dl=1")

QC

Removing cells with total area > 4500 and < 100 \(pixels^2\)
Removing objects with integrated intensity > 5e6 because they tend to be bubbles, precipitated antibody, or debris. It was found that setting minimum area to above 200 pixels^2 predominantly filtered out data from the Ca2+ free control group. Because of this bias in filtering, minimum area was set to > 100 pixels.

o_nrow <- nrow(d)
d <- d[d$total.area < 4500 & d$total.area > 50 & d$w2.stain.integr.intens <5e6,]
message(cat("Current nrow = ",nrow(d),"\nOriginal nrow = ",o_nrow))
Current nrow =  668807 
Original nrow =  683159
message(cat("QC removed",signif(100-(nrow(d)/o_nrow*100),2),"% of cells"))
QC removed 2.1 % of cells

drug2.conc missing in data

Had to remove from keepcols

keepcols <- c("cell.line","drug1","drug1.conc","drug2","well",
              "BRAFi.tx.time","iono.tx.time",
              "cell.id","total.area","positive.w2","w2.stain.area","w2.stain.integr.intens", "avg.pERK")

d <- d[,keepcols]
ab_ctrl_wells <- unique(d[d$drug1=="" & d$drug2=="",]$well)
untx_ctrl_wells <- unique(d[d$drug2=="control",]$well)
ctrl_wells <- c(ab_ctrl_wells,untx_ctrl_wells)

d[is.na(d$drug1.conc),"drug1.conc"] <- 0
d[is.na(d$drug2.conc),"drug2.conc"] <- 0

d[d$drug1=="","drug1"] <- "control"

tx <- tibble(d[!d$well %in% ctrl_wells, ])
tx <- tx[order(tx$BRAFi.tx.time),]

rownames(tx) <- NULL

ctrls <- d[d$well %in% ctrl_wells, ]

tx$drug1.conc <- signif(tx$drug1.conc, digits= 2)
tx$drug1 <- factor(tx$drug1)

Controls

  • drug1 == "holiday": BRAFi-treated cells given a “holiday”; replaced medium with FBS-free, undrugged media
  • drug1 == "persistent": BRAFi maintained, no agonist added
  • drug1 == "control": Drug-naive cells in FBS free medium (no PLX or ionomycin ever added)
  • drug1 == "controlFBS": Drug-naive cells in FBS-containing medium
  • drug1 == "" & drug2 == "": Antibody controls (1° and 2°)
ctrlType <- function(drug1)
    switch(drug1,
           controlFBS="naive_wFBS",
           control="naive_woFBS",
           drug1
           )


d$ctrl_type <- sapply(d$drug1, function(x) 
    ifelse(x %in% c("","control","controlFBS","holiday","persistent"),ctrlType(x),""))

d[d$drug1=="" & is.na(d$drug2),"ctrl_type"] <- "ab_ctrl"
d[d$ctrl_type=="","ctrl_type"] <- NA
d$ctrl_type <- factor(d$ctrl_type)
unique(d$ctrl_type)
[1] naive_woFBS naive_wFBS  <NA>        persistent 
Levels: naive_wFBS naive_woFBS persistent
dtp <- d[!is.na(d$ctrl_type),]
ggplot(dtp, aes(x = avg.pERK, y = ctrl_type, fill = after_stat(x))) + 
    xlim(-1,1.5) + 
    geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
    scale_fill_viridis_c(name = "avg ppERK", option = "C") +
    labs(title = 'Controls', 
         subtitle="") + 
    xlab("Mean ppERK/cell (A.U.)") + ylab("Control condition")

tx <- d[is.na(d$ctrl_type),]
drugs <- unique(tx$drug1)
ppdf <-tx %>%
    group_by(BRAFi.tx.time, drug1, drug1.conc, iono.tx.time, positive.w2) %>%
    summarise(num= n()) 
`summarise()` has grouped output by 'BRAFi.tx.time', 'drug1', 'drug1.conc', 'iono.tx.time'. You can override using the `.groups` argument.
ppdf$positive.w2 <- rep(c("negative","positive"), nrow(ppdf)/2)

pct.pos <- ppdf %>%
    spread(positive.w2, num) %>%
    mutate(total= negative+positive) %>%
    summarise(propos= positive/total) %>%
    ungroup()
`summarise()` has grouped output by 'BRAFi.tx.time', 'drug1', 'drug1.conc'. You can override using the `.groups` argument.
dat <- tx[tx$drug1=="Ionomycin" & tx$BRAFi.tx.time=="3 days",]


g <- lapply(unique(dat$drug1.conc), function(dc) {
    dtp <- dat[dat$drug1.conc==dc,]
    dtp <- dtp[order(dtp$iono.tx.time),]
    
    n_vals <- pct.pos[pct.pos$drug1.conc==dc & pct.pos$BRAFi.tx.time =="3 days" & pct.pos$drug1== "Ionomycin",]
    n_vals$propos <- signif(n_vals$propos*100, 3)
    
    ppERK_vals <- sapply(unique(dtp$iono.tx.time), function(tt) ppERKint(dtp[dtp$iono.tx.time==tt,]))
    names(ppERK_vals) <- unique(dtp$iono.tx.time)
    ppERK_vals <- round(ppERK_vals/ppERK_vals[names(ppERK_vals)=="1"],2)
    
    out <- ggplot(dtp, aes(x = avg.pERK, y = factor(iono.tx.time), fill = after_stat(x))) + 
        xlim(-1,1.5) + 
        geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
        scale_fill_viridis_c(name = "avg ppERK", option = "C") +
        labs(title = 'Drug-tolerant cells', 
             subtitle=paste(unique(dtp$drug1),dc)) + 
        xlab("Mean ppERK/cell (A.U.)") + ylab("Time after Tx") + 
        annotate("text", x=1.5, y=1:(length(ppERK_vals))+0.25, label=ppERK_vals, size=2.5) +
        
        
        annotate("text", x=1.5, y=1.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==1,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=2.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==5,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=3.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==10,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=4.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==15,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=5.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==20,"propos"]), size=2.5) +
        annotate("text", x=1.5, y=1.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==1,])), size=2.5) + 
        annotate("text", x=1.5, y=2.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==5,])), size=2.5) + 
        annotate("text", x=1.5, y=3.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==10,])), size=2.5) + 
        annotate("text", x=1.5, y=4.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==15,])), size=2.5) + 
        annotate("text", x=1.5, y=5.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==20,])), size=2.5) 

    out
})

g
[[1]]

dat <- tx[tx$drug1=="Ionomycin" & tx$BRAFi.tx.time=="60 min",]


g <- lapply(unique(dat$drug1.conc), function(dc) {
    dtp <- dat[dat$drug1.conc==dc,]
    dtp <- dtp[order(dtp$iono.tx.time),]
    
    n_vals <- pct.pos[pct.pos$drug1.conc==dc & pct.pos$BRAFi.tx.time =="60 min"  & pct.pos$drug1== "Ionomycin",]
    n_vals$propos <- signif(n_vals$propos*100, 3)
    
    ppERK_vals <- sapply(unique(dtp$iono.tx.time), function(tt) ppERKint(dtp[dtp$iono.tx.time==tt,]))
    names(ppERK_vals) <- unique(dtp$iono.tx.time)
    ppERK_vals <- round(ppERK_vals/ppERK_vals[names(ppERK_vals)=="1"],2)
    
    out <- ggplot(dtp, aes(x = avg.pERK, y = factor(iono.tx.time), fill = after_stat(x))) + 
        xlim(-1,1.5) + 
        geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
        scale_fill_viridis_c(name = "avg ppERK", option = "C") +
        labs(title = 'Drug-sensitive cells', 
             subtitle=paste(unique(dtp$drug1),dc)) + 
        xlab("Mean ppERK/cell (A.U.)") + ylab("Time after Tx") + 
        annotate("text", x=1.5, y=1:(length(ppERK_vals))+0.25, label=ppERK_vals, size=2.5) +
        
        
        annotate("text", x=1.5, y=1.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==1,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=2.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==5,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=3.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==10,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=4.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==15,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=5.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==20,"propos"]), size=2.5) +
        annotate("text", x=1.5, y=1.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==1,])), size=2.5) + 
        annotate("text", x=1.5, y=2.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==5,])), size=2.5) + 
        annotate("text", x=1.5, y=3.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==10,])), size=2.5) + 
        annotate("text", x=1.5, y=4.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==15,])), size=2.5) + 
        annotate("text", x=1.5, y=5.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==20,])), size=2.5) 

    out
})

g
[[1]]

dat <- tx[tx$drug1=="CPA" & tx$BRAFi.tx.time=="3 days",]


g <- lapply(unique(dat$drug1.conc), function(dc) {
    dtp <- dat[dat$drug1.conc==dc,]
    dtp <- dtp[order(dtp$iono.tx.time),]
    
    n_vals <- pct.pos[pct.pos$drug1.conc==dc & pct.pos$BRAFi.tx.time =="3 days" & pct.pos$drug1== "CPA",]
    n_vals$propos <- signif(n_vals$propos*100, 3)
    
    ppERK_vals <- sapply(unique(dtp$iono.tx.time), function(tt) ppERKint(dtp[dtp$iono.tx.time==tt,]))
    names(ppERK_vals) <- unique(dtp$iono.tx.time)
    ppERK_vals <- round(ppERK_vals/ppERK_vals[names(ppERK_vals)=="1"],2)
    
    out <- ggplot(dtp, aes(x = avg.pERK, y = factor(iono.tx.time), fill = after_stat(x))) + 
        xlim(-1,1.5) + 
        geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
        scale_fill_viridis_c(name = "avg ppERK", option = "C") +
        labs(title = 'Drug-tolerant cells', 
             subtitle=paste(unique(dtp$drug1),dc)) + 
        xlab("Mean ppERK/cell (A.U.)") + ylab("Time after Tx") + 
        annotate("text", x=1.5, y=1:(length(ppERK_vals))+0.25, label=ppERK_vals, size=2.5) +
        
        
        annotate("text", x=1.5, y=1.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==1,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=2.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==5,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=3.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==10,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=4.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==15,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=5.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==20,"propos"]), size=2.5) +
        annotate("text", x=1.5, y=1.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==1,])), size=2.5) + 
        annotate("text", x=1.5, y=2.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==5,])), size=2.5) + 
        annotate("text", x=1.5, y=3.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==10,])), size=2.5) + 
        annotate("text", x=1.5, y=4.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==15,])), size=2.5) + 
        annotate("text", x=1.5, y=5.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==20,])), size=2.5) 

    out
})

g
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

dat <- tx[tx$drug1=="CPA" & tx$BRAFi.tx.time=="60 min",]


g <- lapply(unique(dat$drug1.conc), function(dc) {
    dtp <- dat[dat$drug1.conc==dc,]
    dtp <- dtp[order(dtp$iono.tx.time),]
    
    n_vals <- pct.pos[pct.pos$drug1.conc==dc & pct.pos$BRAFi.tx.time =="60 min"  & pct.pos$drug1== "CPA",]
    n_vals$propos <- signif(n_vals$propos*100, 3)
    
    ppERK_vals <- sapply(unique(dtp$iono.tx.time), function(tt) ppERKint(dtp[dtp$iono.tx.time==tt,]))
    names(ppERK_vals) <- unique(dtp$iono.tx.time)
    ppERK_vals <- round(ppERK_vals/ppERK_vals[names(ppERK_vals)=="1"],2)
    
    out <- ggplot(dtp, aes(x = avg.pERK, y = factor(iono.tx.time), fill = after_stat(x))) + 
        xlim(-1,1.5) + 
        geom_density_ridges_gradient(scale = 3, rel_min_height = 0.01) +
        scale_fill_viridis_c(name = "avg ppERK", option = "C") +
        labs(title = 'Drug-sensitive cells', 
             subtitle=paste(unique(dtp$drug1),dc)) + 
        xlab("Mean ppERK/cell (A.U.)") + ylab("Time after Tx") + 
        annotate("text", x=1.5, y=1:(length(ppERK_vals))+0.25, label=ppERK_vals, size=2.5) +
        
        
        annotate("text", x=1.5, y=1.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==1,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=2.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==5,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=3.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==10,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=4.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==15,"propos"]), size=2.5) + 
        
        annotate("text", x=1.5, y=5.75, label= 
                     paste("%pos =",n_vals[n_vals$iono.tx.time==20,"propos"]), size=2.5) +
        annotate("text", x=1.5, y=1.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==1,])), size=2.5) + 
        annotate("text", x=1.5, y=2.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==5,])), size=2.5) + 
        annotate("text", x=1.5, y=3.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==10,])), size=2.5) + 
        annotate("text", x=1.5, y=4.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==15,])), size=2.5) + 
        annotate("text", x=1.5, y=5.5, label= paste("n =",nrow(dtp[dtp$iono.tx.time==20,])), size=2.5) 

    out
})

g
[[1]]

[[2]]

[[3]]

[[4]]

[[5]]

[[6]]

[[7]]

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCgpgYGB7ciBTZXR1cH0KbGlicmFyeShkaXByYXRlKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodmlyaWRpcykKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3JpZGdlcykKbGlicmFyeShkcGx5cikKYGBgCgojIyMgRnVuY3Rpb24gdG8gcXVhbnRpZnkgcHBFUksgdXNpbmcgYm90aCBwcm9wb3J0aW9uIG9mIHBvc2l0aXZlIGNlbGxzIGFuZCB0aGUgYXZnIGludGVuc2l0eQpVc2luZyBib3RoIHByb3BvcnRpb24gb2YgY2VsbHMgc3RhaW5pbmcgcG9zaXRpdmVseSBmb3IgcHBFUksgYW5kIHRoZSBpbnRlZ3JhdGVkIHZhbHVlcyBvZiB0aGUgcG9zaXRpdmUgY2VsbHMuICAKCmBgYHtyfQpwcEVSS2ludCA8LSBmdW5jdGlvbihkYXQsIHNpZ25pZj00KSB7CiAgICBjZWxsX2NvdW50IDwtIG5yb3coZGF0KQogICAgcG9zX2NlbGxzIDwtIG5yb3coZGF0W2RhdCRwb3NpdGl2ZS53Mj09MSxdKQogICAgdmFsIDwtIHBvc19jZWxscy9jZWxsX2NvdW50KnN1bShkYXRbZGF0JHBvc2l0aXZlLncyPT0xLF0kYXZnLnBFUkspCiAgICB2YWwgPC0gc2lnbmlmKHZhbCxzaWduaWYpCiAgICByZXR1cm4odmFsKQp9CmBgYAoKIyMgTG9hZCBkYXRhCmBgYHtyfQpkIDwtIHJlYWQuY3N2KCJodHRwczovL3d3dy5kcm9wYm94LmNvbS9zY2wvZmkvbXR5M3FiaHR1OTE3cGJydnJhNWtqLzIwMjQwMjExOV9zaW5nbGVjZWxsX2FsbF9jcGEuY3N2P3Jsa2V5PTlmbW40MWZ1MjJwMWwwbHBrd2YxZDIxbncmZGw9MSIpCmBgYAoKCiMgUUMKUmVtb3ZpbmcgY2VsbHMgd2l0aCB0b3RhbCBhcmVhID4gNDUwMCBhbmQgPCAxMDAgJHBpeGVsc14yJCAgClJlbW92aW5nIG9iamVjdHMgd2l0aCBpbnRlZ3JhdGVkIGludGVuc2l0eSA+IDVlNiBiZWNhdXNlIHRoZXkgdGVuZCB0byBiZSBidWJibGVzLCBwcmVjaXBpdGF0ZWQgYW50aWJvZHksIG9yIGRlYnJpcy4KSXQgd2FzIGZvdW5kIHRoYXQgc2V0dGluZyBtaW5pbXVtIGFyZWEgdG8gYWJvdmUgMjAwIHBpeGVsc14yIHByZWRvbWluYW50bHkgZmlsdGVyZWQgb3V0IGRhdGEgZnJvbSB0aGUgQ2EyKyBmcmVlIGNvbnRyb2wgZ3JvdXAuIEJlY2F1c2Ugb2YgdGhpcyBiaWFzIGluIGZpbHRlcmluZywgbWluaW11bSBhcmVhIHdhcyBzZXQgdG8gPiAxMDAgcGl4ZWxzLiAKCmBgYHtyfQpvX25yb3cgPC0gbnJvdyhkKQpkIDwtIGRbZCR0b3RhbC5hcmVhIDwgNDUwMCAmIGQkdG90YWwuYXJlYSA+IDUwICYgZCR3Mi5zdGFpbi5pbnRlZ3IuaW50ZW5zIDw1ZTYsXQptZXNzYWdlKGNhdCgiQ3VycmVudCBucm93ID0gIixucm93KGQpLCJcbk9yaWdpbmFsIG5yb3cgPSAiLG9fbnJvdykpCm1lc3NhZ2UoY2F0KCJRQyByZW1vdmVkIixzaWduaWYoMTAwLShucm93KGQpL29fbnJvdyoxMDApLDIpLCIlIG9mIGNlbGxzIikpCmBgYAoKIyMjIGBkcnVnMi5jb25jYCBtaXNzaW5nIGluIGRhdGEKSGFkIHRvIHJlbW92ZSBmcm9tIGBrZWVwY29sc2AKYGBge3J9CmtlZXBjb2xzIDwtIGMoImNlbGwubGluZSIsImRydWcxIiwiZHJ1ZzEuY29uYyIsImRydWcyIiwid2VsbCIsCiAgICAgICAgICAgICAgIkJSQUZpLnR4LnRpbWUiLCJpb25vLnR4LnRpbWUiLAogICAgICAgICAgICAgICJjZWxsLmlkIiwidG90YWwuYXJlYSIsInBvc2l0aXZlLncyIiwidzIuc3RhaW4uYXJlYSIsIncyLnN0YWluLmludGVnci5pbnRlbnMiLCAiYXZnLnBFUksiKQoKZCA8LSBkWyxrZWVwY29sc10KYGBgCgoKYGBge3J9CmFiX2N0cmxfd2VsbHMgPC0gdW5pcXVlKGRbZCRkcnVnMT09IiIgJiBkJGRydWcyPT0iIixdJHdlbGwpCnVudHhfY3RybF93ZWxscyA8LSB1bmlxdWUoZFtkJGRydWcyPT0iY29udHJvbCIsXSR3ZWxsKQpjdHJsX3dlbGxzIDwtIGMoYWJfY3RybF93ZWxscyx1bnR4X2N0cmxfd2VsbHMpCgpkW2lzLm5hKGQkZHJ1ZzEuY29uYyksImRydWcxLmNvbmMiXSA8LSAwCmRbaXMubmEoZCRkcnVnMi5jb25jKSwiZHJ1ZzIuY29uYyJdIDwtIDAKCmRbZCRkcnVnMT09IiIsImRydWcxIl0gPC0gImNvbnRyb2wiCgp0eCA8LSB0aWJibGUoZFshZCR3ZWxsICVpbiUgY3RybF93ZWxscywgXSkKdHggPC0gdHhbb3JkZXIodHgkQlJBRmkudHgudGltZSksXQoKcm93bmFtZXModHgpIDwtIE5VTEwKCmN0cmxzIDwtIGRbZCR3ZWxsICVpbiUgY3RybF93ZWxscywgXQoKdHgkZHJ1ZzEuY29uYyA8LSBzaWduaWYodHgkZHJ1ZzEuY29uYywgZGlnaXRzPSAyKQp0eCRkcnVnMSA8LSBmYWN0b3IodHgkZHJ1ZzEpCmBgYAoKIyMjIENvbnRyb2xzIAoqIGBkcnVnMSA9PSAiaG9saWRheSJgOiBCUkFGaS10cmVhdGVkIGNlbGxzIGdpdmVuIGEgImhvbGlkYXkiOyByZXBsYWNlZCBtZWRpdW0gd2l0aCBGQlMtZnJlZSwgdW5kcnVnZ2VkIG1lZGlhCiogYGRydWcxID09ICJwZXJzaXN0ZW50ImA6IEJSQUZpIG1haW50YWluZWQsIG5vIGFnb25pc3QgYWRkZWQKKiBgZHJ1ZzEgPT0gImNvbnRyb2wiYDogRHJ1Zy1uYWl2ZSBjZWxscyBpbiBGQlMgZnJlZSBtZWRpdW0gKG5vIFBMWCBvciBpb25vbXljaW4gZXZlciBhZGRlZCkKKiBgZHJ1ZzEgPT0gImNvbnRyb2xGQlMiYDogRHJ1Zy1uYWl2ZSBjZWxscyBpbiBGQlMtY29udGFpbmluZyBtZWRpdW0KKiBgZHJ1ZzEgPT0gIiIgJiBkcnVnMiA9PSAiImA6IEFudGlib2R5IGNvbnRyb2xzICgxwrAgYW5kIDLCsCkgCgpgYGB7cn0KY3RybFR5cGUgPC0gZnVuY3Rpb24oZHJ1ZzEpCiAgICBzd2l0Y2goZHJ1ZzEsCiAgICAgICAgICAgY29udHJvbEZCUz0ibmFpdmVfd0ZCUyIsCiAgICAgICAgICAgY29udHJvbD0ibmFpdmVfd29GQlMiLAogICAgICAgICAgIGRydWcxCiAgICAgICAgICAgKQoKCmQkY3RybF90eXBlIDwtIHNhcHBseShkJGRydWcxLCBmdW5jdGlvbih4KSAKICAgIGlmZWxzZSh4ICVpbiUgYygiIiwiY29udHJvbCIsImNvbnRyb2xGQlMiLCJob2xpZGF5IiwicGVyc2lzdGVudCIpLGN0cmxUeXBlKHgpLCIiKSkKCmRbZCRkcnVnMT09IiIgJiBpcy5uYShkJGRydWcyKSwiY3RybF90eXBlIl0gPC0gImFiX2N0cmwiCmRbZCRjdHJsX3R5cGU9PSIiLCJjdHJsX3R5cGUiXSA8LSBOQQpkJGN0cmxfdHlwZSA8LSBmYWN0b3IoZCRjdHJsX3R5cGUpCnVuaXF1ZShkJGN0cmxfdHlwZSkKYGBgCgpgYGB7cn0KZHRwIDwtIGRbIWlzLm5hKGQkY3RybF90eXBlKSxdCmBgYAoKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZ2dwbG90KGR0cCwgYWVzKHggPSBhdmcucEVSSywgeSA9IGN0cmxfdHlwZSwgZmlsbCA9IGFmdGVyX3N0YXQoeCkpKSArIAogICAgeGxpbSgtMSwxLjUpICsgCiAgICBnZW9tX2RlbnNpdHlfcmlkZ2VzX2dyYWRpZW50KHNjYWxlID0gMywgcmVsX21pbl9oZWlnaHQgPSAwLjAxKSArCiAgICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhuYW1lID0gImF2ZyBwcEVSSyIsIG9wdGlvbiA9ICJDIikgKwogICAgbGFicyh0aXRsZSA9ICdDb250cm9scycsIAogICAgICAgICBzdWJ0aXRsZT0iIikgKyAKICAgIHhsYWIoIk1lYW4gcHBFUksvY2VsbCAoQS5VLikiKSArIHlsYWIoIkNvbnRyb2wgY29uZGl0aW9uIikKCmBgYAoKCgpgYGB7cn0KdHggPC0gZFtpcy5uYShkJGN0cmxfdHlwZSksXQpkcnVncyA8LSB1bmlxdWUodHgkZHJ1ZzEpCmBgYAoKYGBge3J9CnBwZGYgPC10eCAlPiUKICAgIGdyb3VwX2J5KEJSQUZpLnR4LnRpbWUsIGRydWcxLCBkcnVnMS5jb25jLCBpb25vLnR4LnRpbWUsIHBvc2l0aXZlLncyKSAlPiUKICAgIHN1bW1hcmlzZShudW09IG4oKSkgCgoKcHBkZiRwb3NpdGl2ZS53MiA8LSByZXAoYygibmVnYXRpdmUiLCJwb3NpdGl2ZSIpLCBucm93KHBwZGYpLzIpCgpwY3QucG9zIDwtIHBwZGYgJT4lCiAgICBzcHJlYWQocG9zaXRpdmUudzIsIG51bSkgJT4lCiAgICBtdXRhdGUodG90YWw9IG5lZ2F0aXZlK3Bvc2l0aXZlKSAlPiUKICAgIHN1bW1hcmlzZShwcm9wb3M9IHBvc2l0aXZlL3RvdGFsKSAlPiUKICAgIHVuZ3JvdXAoKQpgYGAKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkYXQgPC0gdHhbdHgkZHJ1ZzE9PSJJb25vbXljaW4iICYgdHgkQlJBRmkudHgudGltZT09IjMgZGF5cyIsXQoKCmcgPC0gbGFwcGx5KHVuaXF1ZShkYXQkZHJ1ZzEuY29uYyksIGZ1bmN0aW9uKGRjKSB7CiAgICBkdHAgPC0gZGF0W2RhdCRkcnVnMS5jb25jPT1kYyxdCiAgICBkdHAgPC0gZHRwW29yZGVyKGR0cCRpb25vLnR4LnRpbWUpLF0KICAgIAogICAgbl92YWxzIDwtIHBjdC5wb3NbcGN0LnBvcyRkcnVnMS5jb25jPT1kYyAmIHBjdC5wb3MkQlJBRmkudHgudGltZSA9PSIzIGRheXMiICYgcGN0LnBvcyRkcnVnMT09ICJJb25vbXljaW4iLF0KICAgIG5fdmFscyRwcm9wb3MgPC0gc2lnbmlmKG5fdmFscyRwcm9wb3MqMTAwLCAzKQogICAgCiAgICBwcEVSS192YWxzIDwtIHNhcHBseSh1bmlxdWUoZHRwJGlvbm8udHgudGltZSksIGZ1bmN0aW9uKHR0KSBwcEVSS2ludChkdHBbZHRwJGlvbm8udHgudGltZT09dHQsXSkpCiAgICBuYW1lcyhwcEVSS192YWxzKSA8LSB1bmlxdWUoZHRwJGlvbm8udHgudGltZSkKICAgIHBwRVJLX3ZhbHMgPC0gcm91bmQocHBFUktfdmFscy9wcEVSS192YWxzW25hbWVzKHBwRVJLX3ZhbHMpPT0iMSJdLDIpCiAgICAKICAgIG91dCA8LSBnZ3Bsb3QoZHRwLCBhZXMoeCA9IGF2Zy5wRVJLLCB5ID0gZmFjdG9yKGlvbm8udHgudGltZSksIGZpbGwgPSBhZnRlcl9zdGF0KHgpKSkgKyAKICAgICAgICB4bGltKC0xLDEuNSkgKyAKICAgICAgICBnZW9tX2RlbnNpdHlfcmlkZ2VzX2dyYWRpZW50KHNjYWxlID0gMywgcmVsX21pbl9oZWlnaHQgPSAwLjAxKSArCiAgICAgICAgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJhdmcgcHBFUksiLCBvcHRpb24gPSAiQyIpICsKICAgICAgICBsYWJzKHRpdGxlID0gJ0RydWctdG9sZXJhbnQgY2VsbHMnLCAKICAgICAgICAgICAgIHN1YnRpdGxlPXBhc3RlKHVuaXF1ZShkdHAkZHJ1ZzEpLGRjKSkgKyAKICAgICAgICB4bGFiKCJNZWFuIHBwRVJLL2NlbGwgKEEuVS4pIikgKyB5bGFiKCJUaW1lIGFmdGVyIFR4IikgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTE6KGxlbmd0aChwcEVSS192YWxzKSkrMC4yNSwgbGFiZWw9cHBFUktfdmFscywgc2l6ZT0yLjUpICsKICAgICAgICAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTEuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTEsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT01LCJwcm9wb3MiXSksIHNpemU9Mi41KSArIAogICAgICAgIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9My43NSwgbGFiZWw9IAogICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiJXBvcyA9IixuX3ZhbHNbbl92YWxzJGlvbm8udHgudGltZT09MTAsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT00Ljc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT0xNSwicHJvcG9zIl0pLCBzaXplPTIuNSkgKyAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTIwLCJwcm9wb3MiXSksIHNpemU9Mi41KSArCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0xLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xLF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT01LF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0zLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xMCxdKSksIHNpemU9Mi41KSArIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9NC41LCBsYWJlbD0gcGFzdGUoIm4gPSIsbnJvdyhkdHBbZHRwJGlvbm8udHgudGltZT09MTUsXSkpLCBzaXplPTIuNSkgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTIwLF0pKSwgc2l6ZT0yLjUpIAoKICAgIG91dAp9KQoKZwpgYGAKYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0KZGF0IDwtIHR4W3R4JGRydWcxPT0iSW9ub215Y2luIiAmIHR4JEJSQUZpLnR4LnRpbWU9PSI2MCBtaW4iLF0KCgpnIDwtIGxhcHBseSh1bmlxdWUoZGF0JGRydWcxLmNvbmMpLCBmdW5jdGlvbihkYykgewogICAgZHRwIDwtIGRhdFtkYXQkZHJ1ZzEuY29uYz09ZGMsXQogICAgZHRwIDwtIGR0cFtvcmRlcihkdHAkaW9uby50eC50aW1lKSxdCiAgICAKICAgIG5fdmFscyA8LSBwY3QucG9zW3BjdC5wb3MkZHJ1ZzEuY29uYz09ZGMgJiBwY3QucG9zJEJSQUZpLnR4LnRpbWUgPT0iNjAgbWluIiAgJiBwY3QucG9zJGRydWcxPT0gIklvbm9teWNpbiIsXQogICAgbl92YWxzJHByb3BvcyA8LSBzaWduaWYobl92YWxzJHByb3BvcyoxMDAsIDMpCiAgICAKICAgIHBwRVJLX3ZhbHMgPC0gc2FwcGx5KHVuaXF1ZShkdHAkaW9uby50eC50aW1lKSwgZnVuY3Rpb24odHQpIHBwRVJLaW50KGR0cFtkdHAkaW9uby50eC50aW1lPT10dCxdKSkKICAgIG5hbWVzKHBwRVJLX3ZhbHMpIDwtIHVuaXF1ZShkdHAkaW9uby50eC50aW1lKQogICAgcHBFUktfdmFscyA8LSByb3VuZChwcEVSS192YWxzL3BwRVJLX3ZhbHNbbmFtZXMocHBFUktfdmFscyk9PSIxIl0sMikKICAgIAogICAgb3V0IDwtIGdncGxvdChkdHAsIGFlcyh4ID0gYXZnLnBFUkssIHkgPSBmYWN0b3IoaW9uby50eC50aW1lKSwgZmlsbCA9IGFmdGVyX3N0YXQoeCkpKSArIAogICAgICAgIHhsaW0oLTEsMS41KSArIAogICAgICAgIGdlb21fZGVuc2l0eV9yaWRnZXNfZ3JhZGllbnQoc2NhbGUgPSAzLCByZWxfbWluX2hlaWdodCA9IDAuMDEpICsKICAgICAgICBzY2FsZV9maWxsX3ZpcmlkaXNfYyhuYW1lID0gImF2ZyBwcEVSSyIsIG9wdGlvbiA9ICJDIikgKwogICAgICAgIGxhYnModGl0bGUgPSAnRHJ1Zy1zZW5zaXRpdmUgY2VsbHMnLCAKICAgICAgICAgICAgIHN1YnRpdGxlPXBhc3RlKHVuaXF1ZShkdHAkZHJ1ZzEpLGRjKSkgKyAKICAgICAgICB4bGFiKCJNZWFuIHBwRVJLL2NlbGwgKEEuVS4pIikgKyB5bGFiKCJUaW1lIGFmdGVyIFR4IikgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTE6KGxlbmd0aChwcEVSS192YWxzKSkrMC4yNSwgbGFiZWw9cHBFUktfdmFscywgc2l6ZT0yLjUpICsKICAgICAgICAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTEuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTEsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT01LCJwcm9wb3MiXSksIHNpemU9Mi41KSArIAogICAgICAgIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9My43NSwgbGFiZWw9IAogICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiJXBvcyA9IixuX3ZhbHNbbl92YWxzJGlvbm8udHgudGltZT09MTAsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT00Ljc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT0xNSwicHJvcG9zIl0pLCBzaXplPTIuNSkgKyAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTIwLCJwcm9wb3MiXSksIHNpemU9Mi41KSArCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0xLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xLF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT01LF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0zLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xMCxdKSksIHNpemU9Mi41KSArIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9NC41LCBsYWJlbD0gcGFzdGUoIm4gPSIsbnJvdyhkdHBbZHRwJGlvbm8udHgudGltZT09MTUsXSkpLCBzaXplPTIuNSkgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTIwLF0pKSwgc2l6ZT0yLjUpIAoKICAgIG91dAp9KQoKZwpgYGAKCgpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQpkYXQgPC0gdHhbdHgkZHJ1ZzE9PSJDUEEiICYgdHgkQlJBRmkudHgudGltZT09IjMgZGF5cyIsXQoKCmcgPC0gbGFwcGx5KHVuaXF1ZShkYXQkZHJ1ZzEuY29uYyksIGZ1bmN0aW9uKGRjKSB7CiAgICBkdHAgPC0gZGF0W2RhdCRkcnVnMS5jb25jPT1kYyxdCiAgICBkdHAgPC0gZHRwW29yZGVyKGR0cCRpb25vLnR4LnRpbWUpLF0KICAgIAogICAgbl92YWxzIDwtIHBjdC5wb3NbcGN0LnBvcyRkcnVnMS5jb25jPT1kYyAmIHBjdC5wb3MkQlJBRmkudHgudGltZSA9PSIzIGRheXMiICYgcGN0LnBvcyRkcnVnMT09ICJDUEEiLF0KICAgIG5fdmFscyRwcm9wb3MgPC0gc2lnbmlmKG5fdmFscyRwcm9wb3MqMTAwLCAzKQogICAgCiAgICBwcEVSS192YWxzIDwtIHNhcHBseSh1bmlxdWUoZHRwJGlvbm8udHgudGltZSksIGZ1bmN0aW9uKHR0KSBwcEVSS2ludChkdHBbZHRwJGlvbm8udHgudGltZT09dHQsXSkpCiAgICBuYW1lcyhwcEVSS192YWxzKSA8LSB1bmlxdWUoZHRwJGlvbm8udHgudGltZSkKICAgIHBwRVJLX3ZhbHMgPC0gcm91bmQocHBFUktfdmFscy9wcEVSS192YWxzW25hbWVzKHBwRVJLX3ZhbHMpPT0iMSJdLDIpCiAgICAKICAgIG91dCA8LSBnZ3Bsb3QoZHRwLCBhZXMoeCA9IGF2Zy5wRVJLLCB5ID0gZmFjdG9yKGlvbm8udHgudGltZSksIGZpbGwgPSBhZnRlcl9zdGF0KHgpKSkgKyAKICAgICAgICB4bGltKC0xLDEuNSkgKyAKICAgICAgICBnZW9tX2RlbnNpdHlfcmlkZ2VzX2dyYWRpZW50KHNjYWxlID0gMywgcmVsX21pbl9oZWlnaHQgPSAwLjAxKSArCiAgICAgICAgc2NhbGVfZmlsbF92aXJpZGlzX2MobmFtZSA9ICJhdmcgcHBFUksiLCBvcHRpb24gPSAiQyIpICsKICAgICAgICBsYWJzKHRpdGxlID0gJ0RydWctdG9sZXJhbnQgY2VsbHMnLCAKICAgICAgICAgICAgIHN1YnRpdGxlPXBhc3RlKHVuaXF1ZShkdHAkZHJ1ZzEpLGRjKSkgKyAKICAgICAgICB4bGFiKCJNZWFuIHBwRVJLL2NlbGwgKEEuVS4pIikgKyB5bGFiKCJUaW1lIGFmdGVyIFR4IikgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTE6KGxlbmd0aChwcEVSS192YWxzKSkrMC4yNSwgbGFiZWw9cHBFUktfdmFscywgc2l6ZT0yLjUpICsKICAgICAgICAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTEuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTEsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT01LCJwcm9wb3MiXSksIHNpemU9Mi41KSArIAogICAgICAgIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9My43NSwgbGFiZWw9IAogICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiJXBvcyA9IixuX3ZhbHNbbl92YWxzJGlvbm8udHgudGltZT09MTAsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT00Ljc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT0xNSwicHJvcG9zIl0pLCBzaXplPTIuNSkgKyAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTIwLCJwcm9wb3MiXSksIHNpemU9Mi41KSArCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0xLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xLF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0yLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT01LF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0zLjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xMCxdKSksIHNpemU9Mi41KSArIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9NC41LCBsYWJlbD0gcGFzdGUoIm4gPSIsbnJvdyhkdHBbZHRwJGlvbm8udHgudGltZT09MTUsXSkpLCBzaXplPTIuNSkgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTUuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTIwLF0pKSwgc2l6ZT0yLjUpIAoKICAgIG91dAp9KQoKZwoKCgpkYXQgPC0gdHhbdHgkZHJ1ZzE9PSJDUEEiICYgdHgkQlJBRmkudHgudGltZT09IjYwIG1pbiIsXQoKCmcgPC0gbGFwcGx5KHVuaXF1ZShkYXQkZHJ1ZzEuY29uYyksIGZ1bmN0aW9uKGRjKSB7CiAgICBkdHAgPC0gZGF0W2RhdCRkcnVnMS5jb25jPT1kYyxdCiAgICBkdHAgPC0gZHRwW29yZGVyKGR0cCRpb25vLnR4LnRpbWUpLF0KICAgIAogICAgbl92YWxzIDwtIHBjdC5wb3NbcGN0LnBvcyRkcnVnMS5jb25jPT1kYyAmIHBjdC5wb3MkQlJBRmkudHgudGltZSA9PSI2MCBtaW4iICAmIHBjdC5wb3MkZHJ1ZzE9PSAiQ1BBIixdCiAgICBuX3ZhbHMkcHJvcG9zIDwtIHNpZ25pZihuX3ZhbHMkcHJvcG9zKjEwMCwgMykKICAgIAogICAgcHBFUktfdmFscyA8LSBzYXBwbHkodW5pcXVlKGR0cCRpb25vLnR4LnRpbWUpLCBmdW5jdGlvbih0dCkgcHBFUktpbnQoZHRwW2R0cCRpb25vLnR4LnRpbWU9PXR0LF0pKQogICAgbmFtZXMocHBFUktfdmFscykgPC0gdW5pcXVlKGR0cCRpb25vLnR4LnRpbWUpCiAgICBwcEVSS192YWxzIDwtIHJvdW5kKHBwRVJLX3ZhbHMvcHBFUktfdmFsc1tuYW1lcyhwcEVSS192YWxzKT09IjEiXSwyKQogICAgCiAgICBvdXQgPC0gZ2dwbG90KGR0cCwgYWVzKHggPSBhdmcucEVSSywgeSA9IGZhY3Rvcihpb25vLnR4LnRpbWUpLCBmaWxsID0gYWZ0ZXJfc3RhdCh4KSkpICsgCiAgICAgICAgeGxpbSgtMSwxLjUpICsgCiAgICAgICAgZ2VvbV9kZW5zaXR5X3JpZGdlc19ncmFkaWVudChzY2FsZSA9IDMsIHJlbF9taW5faGVpZ2h0ID0gMC4wMSkgKwogICAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKG5hbWUgPSAiYXZnIHBwRVJLIiwgb3B0aW9uID0gIkMiKSArCiAgICAgICAgbGFicyh0aXRsZSA9ICdEcnVnLXNlbnNpdGl2ZSBjZWxscycsIAogICAgICAgICAgICAgc3VidGl0bGU9cGFzdGUodW5pcXVlKGR0cCRkcnVnMSksZGMpKSArIAogICAgICAgIHhsYWIoIk1lYW4gcHBFUksvY2VsbCAoQS5VLikiKSArIHlsYWIoIlRpbWUgYWZ0ZXIgVHgiKSArIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9MToobGVuZ3RoKHBwRVJLX3ZhbHMpKSswLjI1LCBsYWJlbD1wcEVSS192YWxzLCBzaXplPTIuNSkgKwogICAgICAgIAogICAgICAgIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9MS43NSwgbGFiZWw9IAogICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiJXBvcyA9IixuX3ZhbHNbbl92YWxzJGlvbm8udHgudGltZT09MSwicHJvcG9zIl0pLCBzaXplPTIuNSkgKyAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTIuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTUsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT0zLjc1LCBsYWJlbD0gCiAgICAgICAgICAgICAgICAgICAgIHBhc3RlKCIlcG9zID0iLG5fdmFsc1tuX3ZhbHMkaW9uby50eC50aW1lPT0xMCwicHJvcG9zIl0pLCBzaXplPTIuNSkgKyAKICAgICAgICAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTQuNzUsIGxhYmVsPSAKICAgICAgICAgICAgICAgICAgICAgcGFzdGUoIiVwb3MgPSIsbl92YWxzW25fdmFscyRpb25vLnR4LnRpbWU9PTE1LCJwcm9wb3MiXSksIHNpemU9Mi41KSArIAogICAgICAgIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9NS43NSwgbGFiZWw9IAogICAgICAgICAgICAgICAgICAgICBwYXN0ZSgiJXBvcyA9IixuX3ZhbHNbbl92YWxzJGlvbm8udHgudGltZT09MjAsInByb3BvcyJdKSwgc2l6ZT0yLjUpICsKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTEuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTEsXSkpLCBzaXplPTIuNSkgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTIuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTUsXSkpLCBzaXplPTIuNSkgKyAKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHg9MS41LCB5PTMuNSwgbGFiZWw9IHBhc3RlKCJuID0iLG5yb3coZHRwW2R0cCRpb25vLnR4LnRpbWU9PTEwLF0pKSwgc2l6ZT0yLjUpICsgCiAgICAgICAgYW5ub3RhdGUoInRleHQiLCB4PTEuNSwgeT00LjUsIGxhYmVsPSBwYXN0ZSgibiA9Iixucm93KGR0cFtkdHAkaW9uby50eC50aW1lPT0xNSxdKSksIHNpemU9Mi41KSArIAogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeD0xLjUsIHk9NS41LCBsYWJlbD0gcGFzdGUoIm4gPSIsbnJvdyhkdHBbZHRwJGlvbm8udHgudGltZT09MjAsXSkpLCBzaXplPTIuNSkgCgogICAgb3V0Cn0pCgpnCmBgYAoKCgoK